package cc.rengu.igas.bomp.core.model;

import cc.rengu.igas.bomp.common.constant.BompAppParamConstant;
import cc.rengu.igas.bomp.common.constant.DubboMethodConstant;
import cc.rengu.igas.bomp.common.dao.MchntAcctInfoMapper;
import cc.rengu.igas.bomp.common.dao.impl.MchntAcctInfoMapperImpl;
import cc.rengu.igas.bomp.common.entity.MchntAcctInfo;
import cc.rengu.igas.bomp.common.entity.MchntBaseInfo;
import cc.rengu.igas.bomp.common.entity.MchntSignInfo;
import cc.rengu.igas.bomp.common.enums.AuditStatusEnum;
import cc.rengu.igas.bomp.common.enums.FundTypeEnum;
import cc.rengu.igas.bomp.common.enums.RespCodeEnum;
import cc.rengu.igas.bomp.common.util.InitParamUtil;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.BankAcctInfoQueryRequest;
import cc.rengu.igas.smps.facade.request.GeneralSmsNoticeRequest;
import cc.rengu.igas.smps.facade.response.BankAcctInfoQueryResponse;
import cc.rengu.igas.smps.facade.response.GeneralSmsNoticeResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MsgTemplateCfgMapper;
import cc.rengu.oltp.service.common.dao.SysParamMapper;
import cc.rengu.oltp.service.common.dao.impl.MsgTemplateCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SysParamMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MsgTemplateCfg;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.TemplateTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class EsbIntegration {
    private final RgLogger rglog = RgLog.getLogger(this.getClass().getName());

    public boolean coreAcctSign(MchntBaseInfo mchntBaseInfo, MchntSignInfo mchntSignInfo, TxnInfo txnInfo) {
        try {
            String instId = mchntBaseInfo.getInstId();
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);


            //根据法人行判断是否需要进行签约
            SysParamMapper sysParamMapper = new SysParamMapperImpl();
            SysParam sysParam = sysParamMapper.selectSysParamByPrimaryKey(instId, BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.CORE_ACCT_SIGN);
            if (sysParam == null) {
                rglog.error("根据<instId:{}>,<paramType:{}>,<paramKey:{}>,未查询到系统参数表", instId, BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.CORE_ACCT_SIGN);
                return true;
            }

            //非独立维护商户资料
            if (BompAppParamConstant.FLAG_N.equals(mchntBaseInfo.getIndependentDataFlag())) {
                rglog.error("结算账户核心签约处理失败，该商户为非独立维护商户资料，不需要进行结算账户签约处理,instId:{}, sysSeqNum:{}",
                        instId, sysSeqNum);
                return true;
            }

            MchntAcctInfoMapper mchntAcctInfoMapper = new MchntAcctInfoMapperImpl();
            List<MchntAcctInfo> mchntAcctInfoList = mchntAcctInfoMapper.selectMchntAcctInfoByMchntNo(instId, mchntBaseInfo.getMchntNo());
            if (CollectionUtils.isEmpty(mchntAcctInfoList)) {
                rglog.error("结算账户核心签约失败, 根据商户号查询商户结算账户信息为空，instId:{},mchntNo:{}", instId, mchntBaseInfo.getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }

            //失效旧结算账户信息,解约
            String rebindAcctNo = xmlTreeUtil.getXmlTreeStringValue("rebindAcctNo");
            if (!StringUtil.isEmptyOrNull(rebindAcctNo)) {
                rebindAcctNo(mchntBaseInfo, mchntSignInfo, instId, rebindAcctNo);
            } else if (AuditStatusEnum.CANCEL_AUDIT_SUCCESS.getAuditStatus().equals(mchntBaseInfo.getAuditStatus())) {
                //注销审核通过
                mchntAcctInfoList = mchntAcctInfoList.stream().filter(item -> FundTypeEnum.SETTLE_TYPE.getFundCode().equals(item.getFundType()) && InitParamUtil.isCoreBankType(item.getSettleAcctType())).collect(Collectors.toList());
                //注销审核用过
                if (!CollectionUtils.isEmpty(mchntAcctInfoList)) {
                    rebindAcctNo(mchntBaseInfo, mchntSignInfo, instId, mchntAcctInfoList.get(0).getSettleAcctNo());
                }
                return true;
            }

            //过滤商户结算账户和传入参数的账户信息
            mchntAcctInfoList = mchntAcctInfoList.stream()
                    .filter(item -> BompAppParamConstant.FLAG_N.equals(item.getAcctSignFlag()) && FundTypeEnum.SETTLE_TYPE.getFundCode().equals(item.getFundType())
                            && InitParamUtil.isCoreBankType(item.getSettleAcctType())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(mchntAcctInfoList)) {
                rglog.error("结算账户核心签约处理结束，根据账户查询商户的结算账户表无改结算账户数据或结算账户为他行账户!,instId:{}, sysSeqNum:{},mchntNo:{}",
                        instId, sysSeqNum, mchntBaseInfo.getMchntNo());
                return true;
            }

            if (CollectionUtils.isEmpty(txnInfo.getChannelCallCfgList())) {
                rglog.error("结算账户核心签约处理失败，txnInfo.getchannelCallCfgList 通道服务调用配置表无结算账户核心签约别配置数据!,instId:{}, sysSeqNum:{}",
                        instId, sysSeqNum);
                throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
            }

            //TODO 核心账户签约
            DubboService dubboService = new DubboServiceImpl();

            //查询核心客户号
            BankAcctInfoQueryRequest coreAcctInfoQueryRequest = new BankAcctInfoQueryRequest();
            Header headerQuery = new Header();
            headerQuery.setInstId(mchntBaseInfo.getInstId());
            headerQuery.setTransDate(DateUtil.getCurrentDate());
            headerQuery.setTransTime(DateUtil.getCurrentTime());
            headerQuery.setSrcSysId(AppParamConstant.SYS_ID);
            headerQuery.setChanlId(ChannelEnum.BOMP.getChannelType());
            headerQuery.setTxnNum("00010000200000");
            headerQuery.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(instId));
            coreAcctInfoQueryRequest.setHeader(headerQuery);
            coreAcctInfoQueryRequest.setAcctNo(mchntAcctInfoList.get(0).getSettleAcctNo());
            coreAcctInfoQueryRequest.setCertType(mchntSignInfo.getArtifCertType());
            Result<BankAcctInfoQueryResponse> coreAcctInfoQueryResponse = (Result<BankAcctInfoQueryResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_BANK_SUP_SERVICE, "bankAcctInfoQuery", coreAcctInfoQueryRequest);
            if (null == coreAcctInfoQueryResponse) {
                rglog.error("结算账户核心签约查询处理失败！调用ESB通道的核心账户签约查询coreAcctInfoQueryResponse返回失败!");
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else if (!coreAcctInfoQueryResponse.isSuccess() || !DubboMethodConstant.DUBBO_SUCCESS.equals(coreAcctInfoQueryResponse.getResult().getRespCode())) {
                rglog.error("结算账户核心签约查询处理失败！调用ESB通道的核心账户签约查询coreAcctInfoQueryResponse返回失败,errorCode:{},errorMsg:{}",
                        coreAcctInfoQueryResponse.getResult().getRespCode(), coreAcctInfoQueryResponse.getResult().getRespDesc());
                throw new BizException(coreAcctInfoQueryResponse.getResult().getRespCode(), coreAcctInfoQueryResponse.getResult().getRespDesc());
            }
            updateAcctSignFlag(mchntBaseInfo, sysSeqNum, mchntAcctInfoMapper, mchntAcctInfoList.get(0), coreAcctInfoQueryResponse.getResult());
            return true;
        } catch (Exception e) {
            rglog.error("核心账户签约异常，instId:{},mchntNo:{}, 异常原因:{}",
                    mchntBaseInfo.getInstId(), mchntBaseInfo.getMchntNo(), e.getMessage());
        }

        return false;
    }

    /**
     * 核心解约结算账户
     *
     * @param mchntBaseInfo 商户基本信息
     * @param mchntSignInfo 商户签约信息
     * @param instId        多法人标识
     * @param acctNo        结算账号
     * @throws Exception 异常
     */
    private void rebindAcctNo(MchntBaseInfo mchntBaseInfo, MchntSignInfo mchntSignInfo, String instId, String acctNo) throws Exception {
        //解绑前查询该结算账户是否绑定其他商户
        MchntAcctInfoMapper mchntAcctInfoMapper = new MchntAcctInfoMapperImpl();
        List<MchntAcctInfo> mchntAcctInfoList = mchntAcctInfoMapper.selectMchntAcctInfoByAcctNo(instId, acctNo);
        if (!CollectionUtils.isEmpty(mchntAcctInfoList)) {
            //仍有商户使用该结算账户，按审核状态进行过滤(过滤非正式商户数据)
            List<MchntAcctInfo> normalAcctInfoList = mchntAcctInfoList.stream()
                    .filter(item -> !(AuditStatusEnum.BE_AUDIT.getAuditStatus().equals(item.getAuditStatus())
                            || AuditStatusEnum.ADD_BE_AUDIT.getAuditStatus().equals(item.getAuditStatus())
                            || AuditStatusEnum.ADD_AUDIT_REJECT.getAuditStatus().equals(item.getAuditStatus())
                            || AuditStatusEnum.CANCEL_AUDIT_SUCCESS.getAuditStatus().equals(item.getAuditStatus()))).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(normalAcctInfoList)) {
                rglog.error("不允许解绑，存在商户仍使用该结算账户，acctNo:{}", acctNo);
            } else {
                //没有数据
                rglog.debug("允许解绑，无正式商户使用该结算账户，acctNo:{}", acctNo);
            }
        }
        //TODO 解约
    }

    private void updateAcctSignFlag(MchntBaseInfo mchntBaseInfo, String sysSeqNum,
                                    MchntAcctInfoMapper mchntAcctInfoMapper, MchntAcctInfo mchntAcctInfo,
                                    BankAcctInfoQueryResponse coreAcctInfoQueryResponse) throws Exception {

        //核心客户号
        mchntAcctInfo.setCoreCustomerId(coreAcctInfoQueryResponse.getCoreCustomerNo());
        mchntAcctInfo.setAcctSignFlag(BompAppParamConstant.FLAG_Y);
        mchntAcctInfo.setLastOprId(mchntBaseInfo.getLastOprId());
        mchntAcctInfo.setLastUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        int dbResult = mchntAcctInfoMapper.updateAcctSignFlagById(mchntAcctInfo);
        if (dbResult != 0) {
            rglog.error("更新商户结算信息表核心账户签约标识失败,sysSeqNum:<{}>,iReturnCode:<{}>",
                    sysSeqNum, dbResult);
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 商户申请审核通过(商户)
     *
     * @param mchntBaseInfo 商户
     * @param txnInfo       交易信息
     * @return true-通过,false-不通过
     */
    public boolean sendSmsMsg(MchntBaseInfo mchntBaseInfo, TxnInfo txnInfo) {
        try {
            if (!AuditStatusEnum.ADD_AUDIT_SUCCESS.getAuditStatus().equals(mchntBaseInfo.getAuditStatus())) {
                //除新增外，其余场景不需要发送短信
                return true;
            }

            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam sysParam = sysParamService.getSysParamInfo(mchntBaseInfo.getInstId(), BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.INST_ADD_MCHNT_AUDIT_PASS_SMS);
            if (null == sysParam) {
                //法人行无需发送短信
                rglog.info("新增审核通过，该法人行无需发送短信。instId:{}", mchntBaseInfo.getInstId());
                return true;
            }

            GeneralSmsNoticeRequest generalSmsNoticeRequest = new GeneralSmsNoticeRequest();
            List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> "00450000000E01".equals(item.getCallChannelTxn())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(channelCallCfgList)) {
                rglog.info("新增审核通过，该法人行需要发送短信，但配置的交易映射码关系无发送短信服务 00450000000E01 。MchntNo:{}", mchntBaseInfo.getMchntNo());
                return false;
            }

            /* 获取短信模板 */
            MsgTemplateCfgMapper msgTemplateCfgMapper = new MsgTemplateCfgMapperImpl();
            MsgTemplateCfg msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(mchntBaseInfo.getInstId(), TemplateTypeEnum.SMS_MCHNT_APPLY_AUDIT_PASS_FOR_MCHNT.getTemplateType());
            if (null == msgTemplateCfg) {
                msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(AppParamConstant.DEFAULT_INSTID, TemplateTypeEnum.SMS_MCHNT_APPLY_AUDIT_PASS_FOR_MCHNT.getTemplateType());
                if (null == msgTemplateCfg) {
                    rglog.error("未配置新增商户审核通过成功后向商户发送短信通知的短信模板，instId:<{}>", mchntBaseInfo.getInstId());
                    return false;
                }
            }
            rglog.debug("短信模板代码:<{}>,短信模板内容:<{}>", msgTemplateCfg.getTemplateCode(), msgTemplateCfg.getTemplateDesc());

            //短信内容  恭喜您在我行申请的商户通过审核,请牢记分配您的商户号:[xxxx],您可登录商户服务平台进行相关操作
            String smsContent = parseSmsTemplateInfo(msgTemplateCfg.getTemplateDesc(), mchntBaseInfo.getMchntNo());
            rglog.debug("短信内容：{}", smsContent);

            ChannelCallCfg channelCallCfg = channelCallCfgList.get(0);
            Header header = new Header();
            header.setInstId(mchntBaseInfo.getInstId());
            header.setTransDate(DateUtil.getCurrentDate());
            header.setTransTime(DateUtil.getCurrentTime());
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setChanlId(ChannelEnum.BOMP.getChannelType());
            header.setTxnNum(channelCallCfg.getCallChannelTxn());
            header.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntBaseInfo.getInstId()));
            generalSmsNoticeRequest.setHeader(header);
            generalSmsNoticeRequest.setRealtimeFlag(AppParamConstant.YES); //实时发送
            List<String> phoneNoList = new ArrayList<>();
            phoneNoList.add(mchntBaseInfo.getMchntContactMobile());
            generalSmsNoticeRequest.setPhoneList(phoneNoList); //联系人手机号
            generalSmsNoticeRequest.setTemplateId(msgTemplateCfg.getTemplateCode());
            generalSmsNoticeRequest.setSmsContent(smsContent);

            DubboService dubboService = new DubboServiceImpl();
            Result<GeneralSmsNoticeResponse> smsResult = (Result<GeneralSmsNoticeResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_SMS_SERVICE, "smsMsgPush", generalSmsNoticeRequest);
            if (null == smsResult || !smsResult.isSuccess() || !DubboMethodConstant.DUBBO_SUCCESS.equals(smsResult.getResult().getRespCode())) {
                rglog.error("调用短信平台发送短信通知失败:{}", JSON.toJSONString(smsResult));
                return false;
            }
            return true;
        } catch (Exception e) {
            rglog.error("商户审核发送短信异常，instId:{},mchntNo:{}, 异常原因:{}",
                    mchntBaseInfo.getInstId(), mchntBaseInfo.getMchntNo(), e.getMessage());
        }
        return false;
    }

    /**
     * 动态解析短信模板生成短信内容
     *
     * @param templateDesc 短信模板内容
     * @return 短信内容
     */
    private String parseSmsTemplateInfo(String templateDesc, String mchntNo) {
        StringBuilder stringBuilder = new StringBuilder();
        while (!cc.rengu.oltp.utility.util.StringUtil.isEmptyOrNull(templateDesc) && templateDesc.contains("[")) {
            int startIndex = templateDesc.indexOf("[");
            stringBuilder.append(templateDesc, 0, startIndex);
            templateDesc = templateDesc.substring(startIndex + 1);
            int endIndex = templateDesc.indexOf("]");
            stringBuilder.append(mchntNo);
            templateDesc = templateDesc.substring(endIndex + 1);
        }
        stringBuilder.append(templateDesc);
        return stringBuilder.toString();
    }
}
